﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Framework.Core.Dependency.Domain;

namespace Framework.Core.Dependency.Parser
{
    internal class Vb6ProjectParser : IStreamParser<Solution>
    {
        private static readonly Regex RegexReferences =
            new Regex(
                @"^[^=\s]*=((.){2}[G]{1})*(?<Guid>{.*})#(?<Version1>[^#]*)#(?<Version2>[^#;]*)[#;]{1,2}\s*(?<LibPath>[^#]*)",
                RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

        public Solution Parse(Stream stream, string filePath, string branch)
        {
            using (var reader = new StreamReader(stream))
            {
                var content = reader.ReadToEnd();

                Solution solution = null;

                var modules = new List<Module>();

                var lines = content.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

                var files = new List<string>();

                Project project = null;

                const string exeName32Tag = "ExeName32=";

                var assemblyNameTag = lines.Any(l => l.Contains(exeName32Tag)) ? exeName32Tag : "Name=";

                foreach (var line in lines)
                {
                    if (line.StartsWith("Form=") || line.StartsWith("Module=") || line.StartsWith("Class=") ||
                        line.StartsWith("UserControl="))
                    {
                        files.Add(Regex.Replace(line, @"^[^\=]*\=", string.Empty).Split(new[] { ';' }).Last());
                    }

                    if (line.StartsWith(assemblyNameTag))
                    {
                        var assemblyName = Path.GetFileNameWithoutExtension(line.Replace(assemblyNameTag, string.Empty).Replace(@"""", string.Empty));
                        solution = new Solution(Path.GetFileNameWithoutExtension(filePath),
                                                Path.GetExtension(filePath),
                                                filePath,
                                                Language.Vb6,
                                                branch);
                        project = new Project(solution.Name,
                                              solution.Extension,
                                              filePath,
                                              assemblyName,
                                              solution.Language);
                    }
                    var match = RegexReferences.Match(line);

                    if (match.Success)
                    {
                        var libPath = match.Groups["LibPath"].Value;
                        var name = libPath.Split(new[] { @"\" }, StringSplitOptions.RemoveEmptyEntries).Last();
                        var assemblyName = Path.GetFileNameWithoutExtension(name);
                        modules.Add(new Module(assemblyName, libPath));
                    }
                }

                // ReSharper disable PossibleNullReferenceException
                files.ForEach(project.Files.Add);
                modules.ForEach(project.AddModule);
                solution.AddProject(project, branch);
                // ReSharper restore PossibleNullReferenceException

                return solution;
            }
        }
    }
}